package net.ib.mtalk.ui.attachment.vcard;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.telephony.PhoneNumberUtils;
import android.text.SpannableStringBuilder;

/**
 * vCard 주소를 저장할 데이터 구조체
 * 폰푹에 의존적이다.
 * API Level 7 로 설계 
 * @author happy2v
 *
 */
public class ContactStruct {
	
	// 다중으로 사용할 아이템 ADD로 아이템을 추가한다.
	public static final int KIND_EMAIL 			= 0x01;
	public static final int KIND_POSTAL 		= 0x02;
	public static final int KIND_IM 			= 0x03;	
	public static final int KIND_ORGANIZATION	= 0x04;
	public static final int KIND_PHONE 			= 0x05;
	public static final int KIND_NOTE			= 0x06;			// String NOTE(DATA1)
	
	// 추가하지 않은 주소록 공통 데이터 
	public static final int KIND_NAME			= 0x11;
	public static final int KIND_NICKNAME		= 0x12;			// String NAME(DATA1), int TYPE(DATA2), String LABEL(DATA3)
	public static final int KIND_GROUP_MEMBERSHIP = 0x13;		// long GROUP_ROW_ID(DATA1), String GROUP_SOURCE_ID
	public static final int KIND_WEBSITE		= 0x14;			// String URL(DATA1), int TYPE(DATA2), String LABEL(DATA3)
	public static final int KIND_EVENT			= 0x15;			// String START_DATE(DATA1), int TYPE(DATA2), String LABEL(DATA3)
	public static final int KIND_PHOTO			= 0x16;			// BLOB PHOTO(DATA1)
	public static final int KIND_RELATION		= 0x17;			// String NAME(DATA1), int TYPE(DATA2), String LABEL(DATA3)
	public static final int KIND_SIP_ADDRESS	= 0x18;			// API LEVEL 9
	
    /**
     * 이름 (반드시 존재)
     */
    public String name;
    /**
     * 성 + 이름
     */
    public String fullName;
    /**
     * 사진 (byte[])
     */
    public byte[] photoBytes;
    /**
     * 사진의 타입
     */
    public String photoType;
    /**
     * 회사 정보
     */
    public String company;
    /**
     * 제목
     */
    public String title;
	/**
	 * 전화번호 리스트
	 * addPhone(int type, String number, String label, boolean isPrimary)
	 */
	public List<PhoneData> phoneList;
	/**
	 * 이 메일 리스트
	 * addEmail(int type, String data, String label, boolean isPrimary)
	 */
	public List<EmailData> emailList;
	/**
	 * 주소 리스트
	 * addPostal(int type, List<String> propValueList, String label, String formattedAddress, boolean isPrimary)
	 * List<String> propValueList {street, pobox, neighborhood, city, region, postalCode, country}
	 * 순서대로 입력, 7개가 넘을경우 나중에 등록된 리스트아이템은 사용하지 않음.
	 */
	public List<PostalData> postalList;
	/**
	 * 메신져 리스트
	 * addImData(int protocol, String customProtocol, int type, String data, String label, boolean isPrimary)
	 */
	public List<ImData> imList;
	/**
	 * 조직도 리스트
	 * addOrganization(int type, List<String> propValueList, String label, String company, boolean isPrimary)
	 * List<String> propValueList {title, department, jobDescription, symbol, phoneticName, officeLocation, phoneticNameStyle}
	 * 순서대로 입력, 7개가 넘을경우 나중에 등록된 리스트아이템은 사용하지 않음.
	 */
	public List<OrganizationData> organizationList;
	/**
	 * 메모
	 * addNote(String note)
	 */
	public List<NoteData> noteList;
	/**
	 * 메소드 리스트
	 * addContactMethod(int type, String data, String label, int kind, boolean isPrimary)
	 */
    public List<ContactMethod> contactmethodList;
	/**
	 * 전화번호 정보
	 */
	public static class PhoneData{
		public final int type;
		public final String number;
		public final String label;
		public boolean isPrimary;
		
		/**
		 * 전화번호 정보 설정
		 * @param type			타입
		 * @param _number		전화번호
		 * @param label			라벨
		 * @param isPrimary		기본 전화번호인지 확인
		 */
		public PhoneData(int type, String _number, String label, boolean isPrimary){
			this.type = type;
			this.number = _number;
			this.label = label;
			this.isPrimary = isPrimary;
		}
		
		@Override
		public boolean equals(Object obj){
			if(!(obj instanceof PhoneData)){
				return false;
			}
			PhoneData phoneData = (PhoneData)obj;
			return (type == phoneData.type && number.equals(phoneData.number) &&
					label.equals(phoneData.label) && isPrimary == phoneData.isPrimary);
		}
		
		@Override
		public String toString(){
			return String.format("type: %d, data: %s, label: %s, isPrimary: %s", type, number, label, isPrimary);
		}
	}
	/**
	 * 이메일 정보
	 */
	public static class EmailData{
		public final int type;
		public final String address;
		public final String label;
		public boolean isPrimary;
		
		/**
		 * 이메일 정보 설정
		 * @param type			타입
		 * @param _address		이메일 주소
		 * @param label			라벨
		 * @param isPrimary		기본 메일인지 확인
		 */
		public EmailData(int type, String _address, String label, boolean isPrimary){
			this.type = type;
			this.address = _address;
			this.label = label;
			this.isPrimary = isPrimary;
		}
		
		@Override
		public boolean equals(Object obj){
			if(!(obj instanceof EmailData)){
				return false;
			}
			EmailData emailData = (EmailData)obj;
			return (type == emailData.type && address.equals(emailData.address) &&
					label.equals(emailData.label) && isPrimary == emailData.isPrimary);
		}
		
		@Override
		public String toString(){
			return String.format("type: %d, data: %s, label: %s, isPrimary: %s", type, address, label, isPrimary);
		}
	}
	/**
	 * 주소 정보
	 */
	public static class PostalData{
        public static final int ADDR_MAX_DATA_SIZE = 7;
        private final String[] dataArray;
        public final int type;
        public final String formattedAddress;	//FORMATTED_ADDRESS
        public final String label;
        public final String street;				//STREET
        public final String pobox;				//POBOX
        public final String neighborhood;		//NEIGHBORHOOD
        public final String city;				//CITY
        public final String region;				//REGION
        public final String postalCode;			//POSTCODE
        public final String country;			//COUNTRY
        public boolean isPrimary;

        /**
         * 주소 정보 설정
         * @param type					타입
         * @param propValueList			주소의 아이템 배열
         * @param label					라벨
         * @param _formattedAddress		풀 주소
         * @param isPrimary				기본 주소인지 확인
         */
        public PostalData(final int type, final List<String> propValueList,
                final String label, final String _formattedAddress, boolean isPrimary) {
            dataArray = new String[ADDR_MAX_DATA_SIZE];

            int size = propValueList.size();
            if (size > ADDR_MAX_DATA_SIZE) {
                size = ADDR_MAX_DATA_SIZE;
            }

            int i = 0;
            for (String addressElement : propValueList) {
                dataArray[i] = addressElement;
                if (++i >= size) {
                    break;
                }
            }
            while (i < ADDR_MAX_DATA_SIZE) {
                dataArray[i++] = null;
            }

            this.pobox 				= dataArray[0];
            this.neighborhood 		= dataArray[1];
            this.street				= dataArray[2];
            this.city 				= dataArray[3];
            this.region 			= dataArray[4];
            this.postalCode 		= dataArray[5];
            this.country 			= dataArray[6];
            this.type 				= type;
            this.formattedAddress 	= _formattedAddress;
            this.label 				= label;
            this.isPrimary 			= isPrimary;
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof PostalData)) {
                return false;
            }
            final PostalData postalData = (PostalData)obj;
            return (Arrays.equals(dataArray, postalData.dataArray) &&
                    (type == postalData.type &&
                            (type == StructuredPostal.TYPE_CUSTOM ?
                                    (label == postalData.label) : true)) &&
                    (isPrimary == postalData.isPrimary));
        }

        @Override
        public String toString() {
            return String.format("type: %d, label: %s, isPrimary: %s",
                    type, label, isPrimary);
        }
	}
	/**
	 * 메신져 정보
	 */
	public static class ImData {
        public final int protocol;
        public final String customProtocol;
        public final int type;
        public final String data;
        public final String label;
        public boolean isPrimary;

        public ImData(final int protocol, final String customProtocol, final int type,
                final String data, final String label, final boolean isPrimary) {
        	this.protocol = protocol;
            this.customProtocol = customProtocol;
            this.type = type;
            this.data = data;
            this.label = label;
            this.isPrimary = isPrimary;
        }

        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof ImData)) {
                return false;
            }
            ImData imData = (ImData)obj;
            return (type == imData.type && protocol == imData.protocol
                    && (customProtocol != null ? customProtocol.equals(imData.customProtocol) :
                        (imData.customProtocol == null))
                    && (data != null ? data.equals(imData.data) : (imData.data == null))
                    && label == imData.label
                    && isPrimary == imData.isPrimary);
        }

        @Override
        public String toString() {
            return String.format(
                    "type: %d, protocol: %d, custom_protcol: %s, data: %s, isPrimary: %s",
                    type, protocol, customProtocol, data, isPrimary);
        }
    }
	/**
	 * 조직도 정보
	 */
	public static class OrganizationData {
		public final int type;
		public final String label;
		public final String company;
		public final String title;						// TITLE
		public final String department;					// DEPARTMENT
		public final String jobDescription;				// JOB_DESCRIPTION
		public final String symbol;						// SYMBOL
		public final String phoneticName;				// PHONETIC_NAME
		public final String officeLocation;				// OFFICE_LOCATION
		public final String phoneticNameStyle;			// PHONETIC_NAME_STYLE
		public boolean isPrimary;

        public static final int ADDR_MAX_DATA_SIZE = 7;
        private final String[] dataArray;
		
		public OrganizationData(final int type, final List<String> propValueList,
                final String label, final String company, boolean isPrimary) {
            dataArray = new String[ADDR_MAX_DATA_SIZE];

            int size = propValueList.size();
            if (size > ADDR_MAX_DATA_SIZE) {
                size = ADDR_MAX_DATA_SIZE;
            }

            int i = 0;
            for (String organizationElement : propValueList) {
                dataArray[i] = organizationElement;
                if (++i >= size) {
                    break;
                }
            }
            while (i < ADDR_MAX_DATA_SIZE) {
                dataArray[i++] = null;
            }

            this.title 				= dataArray[0];
            this.department 		= dataArray[1];
            this.jobDescription		= dataArray[2];
            this.symbol 			= dataArray[3];
            this.phoneticName 		= dataArray[4];
            this.officeLocation 	= dataArray[5];
            this.phoneticNameStyle 	= dataArray[6];
            this.type 				= type;
            this.company 			= company;
            this.label 				= label;
            this.isPrimary 			= isPrimary;
        }
		
		@Override
        public boolean equals(Object obj) {
            if (!(obj instanceof OrganizationData)) {
                return false;
            }
            final OrganizationData organizationData = (OrganizationData)obj;
            return (Arrays.equals(dataArray, organizationData.dataArray)
            		&& (type == organizationData.type 
            				&& (type == Organization.TYPE_CUSTOM ?
                                    (label == organizationData.label) : true)) 
                    && company == organizationData.company
                    && (isPrimary == organizationData.isPrimary));
        }

        @Override
        public String toString() {
            return String.format("type: %d, label: %s, company: %s, isPrimary: %s",
                    type, label, company, isPrimary);
        }
	}
	/**
	 * 메모 정보
	 */
	public static class NoteData{
		public final String note;
		public boolean isPrimary;
		
		public NoteData(String note, boolean isPrimary){
			this.note = note;
			this.isPrimary = isPrimary;
		}
		
		@Override
        public boolean equals(Object obj) {
            if (!(obj instanceof NoteData)) {
                return false;
            }
            NoteData noteData = (NoteData)obj;
            return (note == noteData.note
                    && isPrimary == noteData.isPrimary);
        }
		
		@Override
		public String toString(){
			return String.format("note: %s, isPrimary: %s", note, isPrimary);
		}
	}
	
	/**
	 * 메소드 정보
	 */
	public static class ContactMethod{
		public final int type;
		public final String data;
		public final String label;
		public final int kind;
		public boolean isPrimary;
		public boolean isSelected = false;
		public ContactMethod(int type, String data, String label, int kind, boolean isPrimary){
			this.type = type;
			this.data = data;
			this.label = label;
			this.kind = kind;
			this.isPrimary = isPrimary;
		}
		
		@Override
		public boolean equals(Object obj){
			if(!(obj instanceof ContactMethod)){
				return false;
			}
			ContactMethod contactMethod = (ContactMethod)obj;
			return (type == contactMethod.type && data.equals(contactMethod.data) &&
					label.equals(contactMethod.label) && kind == contactMethod.kind
					&&  isPrimary == contactMethod.isPrimary);
		}
		
		@Override
		public String toString(){
			return String.format("type: %d, data: %s, label: %s, kind: %d, isPrimary: %s", type, data, label, kind, isPrimary);
		}
	}

	/**
	 * 전화번호를 추가한다.
	 * @param type 전화번호의 타입
	 * @param number 전화번호
	 * @param label 전화번호의 이름
	 * @param isPrimary
	 */
	public void addPhone(int type, String number, String label, boolean isPrimary) {
        if (phoneList == null) {
        	phoneList = new ArrayList<PhoneData>();
        }
        final StringBuilder builder = new StringBuilder();
        final String trimed = number.trim();
        final String formattedNumber;
        if (type == Phone.TYPE_PAGER) {
            formattedNumber = trimed;
        } else {
            final int length = trimed.length();
            for (int i = 0; i < length; i++) {
                char ch = trimed.charAt(i);
                if (('0' <= ch && ch <= '9') || (i == 0 && ch == '+')) {
                    builder.append(ch);
                }
            }

            final int formattingType = PhoneNumberUtils.FORMAT_NANP;
            formattedNumber = formatNumber(builder.toString(), formattingType);
        }
        PhoneData phoneData = new PhoneData(type, formattedNumber, label, isPrimary);
        phoneList.add(phoneData);
	}
		
	public static String formatNumber(String source, int defaultFormattingType) {
        SpannableStringBuilder text = new SpannableStringBuilder(source);
        PhoneNumberUtils.formatNumber(text, defaultFormattingType);
        return text.toString();
    }
		
	/**
	 * 이메일을 추가한다.
	 * @param type 이메일의 타입
	 * @param data 이메일의 데이터
	 * @param label 이메일의 이름
	 * @param isPrimary
	 */
	public void addEmail(int type, String data, String label, boolean isPrimary){
        if (emailList == null) {
        	emailList = new ArrayList<EmailData>();
        }
        emailList.add(new EmailData(type, data, label, isPrimary));
    }
	
	/**
	 * 주소를 추가한다.
	 * @param type 주소의 타입
	 * @param propValueList 주소의 데이터
	 * @param label 주소의 이름
	 * @param formattedAddress 풀네임 주소
	 * @param isPrimary
	 */
	public void addPostal(int type, List<String> propValueList, String label, String formattedAddress, boolean isPrimary){
        if (postalList == null) {
        	postalList = new ArrayList<PostalData>();
        }
        postalList.add(new PostalData(type, propValueList, label, formattedAddress, isPrimary));
    }
	
	/**
	 * 메신져를 추가한다.
	 * @param protocol 메신져 프로토콜
	 * @param customProtocol
	 * @param type 메신져 타입
	 * @param data 메신져 주소
	 * @param label 라벨
	 * @param isPrimary 
	 */
	public void addImData(int protocol, String customProtocol, int type, String data, String label, boolean isPrimary){
		if(imList == null){
			imList = new ArrayList<ImData>();
		}
		imList.add(new ImData(protocol, customProtocol, type, data, label, isPrimary));
	}
	
	/**
	 * 조직도를 추가한다.
	 * @param type 조직도 타입
	 * @param propValueList	조직도 데이터
	 * @param label	조직도의 이름
	 * @param company	회사 이름
	 * @param isPrimary
	 */
	public void addOrganization(int type, List<String> propValueList, String label, String company, boolean isPrimary){
        if (organizationList == null) {
        	organizationList = new ArrayList<OrganizationData>();
        }
        organizationList.add(new OrganizationData(type, propValueList, label, company, isPrimary));
    }
	
	/**
	 * 메모를 추가한다.
	 * @param note 메모
	 */
	public void addNote(String note, boolean isPrimary){
		if(noteList == null){
			noteList = new ArrayList<NoteData>();
		}
		noteList.add(new NoteData(note, isPrimary));
	}
	
	/**
	 * 기타 메소드를 추가한다.
	 * @param type 메소드 타입
	 * @param data 메소드 데이터
	 * @param label 메소드 이름
	 * @param kind 메소드 종류
	 * @param isPrimary
	 */
	public void addContactMethod(int type, String data, String label, int kind, boolean isPrimary){
		if(contactmethodList == null){
			contactmethodList = new ArrayList<ContactMethod>(0);
		}
		contactmethodList.add(new ContactMethod(type, data, label, kind, isPrimary));
	}
	
	
	/**
	 * 이름 설정(디스플레이 네임과, 기본 네임만 사용)
	 * @param name
	 * @param fullName
	 */
	public void setName(String name, String fullName){
		this.name = name;
		this.fullName = fullName;
	}
	
	/**
	 * 프로필 사진 설정(타입과 바이트배열로 설정)
	 * @param photo byte[]
	 * @param type String
	 */
	public void setPhoto(byte[] photo, String type){
		this.photoBytes = photo;
		this.photoType = type;
	}
	
	/**
	 * 타이틀 설정
	 * @param title
	 */
	public void setTitle(String title){
		this.title = title;
	}
}